﻿using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ViewFaceCore.Model;

namespace OcrWinForm.Extensions
{
    public static class ViewFaceSkiaSharpExtension
    {
        private const SKColorType targetColorType = SKColorType.Bgra8888;

        //
        // 摘要:
        //     SKBitmap convert to FaceImage
        //
        // 参数:
        //   image:
        public static FaceImage ToFaceImage(this SKBitmap image)
        {
            int width;
            int height;
            int channels;
            byte[] buffer = To24BGRByteArray(image, out width, out height, out channels);
            return new FaceImage(width, height, channels, buffer);
        }

        //
        // 摘要:
        //     SKBitmap convert to FaceImage
        //
        // 参数:
        //   obj:
        //
        // 类型参数:
        //   T:
        //     Only support type of SkiaSharp.SKBitmap
        //
        // 异常:
        //   T:System.NotImplementedException:
        public static FaceImage ToFaceImage<T>(this T obj) where T : class
        {
            if (obj == null)
            {
                throw new ArgumentNullException("obj");
            }

            if (obj is SKBitmap image)
            {
                return image.ToFaceImage();
            }

            throw new Exception($"Not support type:{obj.GetType()}");
        }

        //
        // 摘要:
        //     Bitmap 转为 3*8bit BGR System.Byte 数组。
        //
        // 参数:
        //   source:
        //     待转换图像
        //
        //   width:
        //     图像宽度
        //
        //   height:
        //     图像高度
        //
        //   channels:
        //     图像通道
        //
        // 返回结果:
        //     图像的 BGR System.Byte 数组
        private static byte[] To24BGRByteArray(SKBitmap source, out int width, out int height, out int channels)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            channels = 3;
            if (source.ColorType != SKColorType.Bgra8888)
            {
                using (SKBitmap sKBitmap = ConvertToBgra8888(source))
                {
                    width = sKBitmap.Width;
                    height = sKBitmap.Height;
                    return ConvertToByte(sKBitmap, channels);
                }
            }

            width = source.Width;
            height = source.Height;
            return ConvertToByte(source, channels);
        }

        //
        // 摘要:
        //     转换图像格式
        //
        // 参数:
        //   source:
        //
        // 异常:
        //   T:System.Exception:
        private static SKBitmap ConvertToBgra8888(SKBitmap source)
        {
            if (!source.CanCopyTo(SKColorType.Bgra8888))
            {
                throw new Exception("Can not copy image color type to Bgra8888");
            }

            SKBitmap sKBitmap = new SKBitmap();
            source.CopyTo(sKBitmap, SKColorType.Bgra8888);
            if (sKBitmap == null)
            {
                throw new Exception("Copy image to Bgra8888 failed");
            }

            return sKBitmap;
        }

        //
        // 摘要:
        //     转为BGR Bytes
        //
        // 参数:
        //   source:
        //
        //   channels:
        //
        // 异常:
        //   T:System.Exception:
        private static byte[] ConvertToByte(SKBitmap source, int channels)
        {
            byte[] bytes = source.Bytes;
            if (bytes == null || bytes.Length == 0)
            {
                throw new Exception("SKBitmap data is null");
            }

            byte[] array = new byte[bytes.Length / 4 * channels];
            int num = 0;
            for (int i = 0; i < bytes.Length; i++)
            {
                if ((i + 1) % 4 != 0)
                {
                    array[num] = bytes[i];
                    num++;
                }
            }

            return array;
        }
    }
}
